package de.slothsoft.android4swing;

import java.io.IOException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.ResourceBundle;
import java.util.Vector;

public class AndroidResourceBundle extends ResourceBundle {

    private static Map<String, ResourceBundle> cache = new HashMap<>();

    public static ResourceBundle getAndroidBundle(String bundlePath) {
	return getAndroidBundle(bundlePath, Locale.getDefault());
    }

    public synchronized static ResourceBundle getAndroidBundle(String bundlePath, Locale locale) {
	String key = bundlePath + "/" + locale.getLanguage();
	ResourceBundle result = cache.get(key);
	if (result == null) {
	    result = new AndroidResourceBundle(bundlePath, locale);
	    cache.put(key, result);
	}
	return result;
    }

    private final String bundlePath;
    protected final Locale locale;
    private final Map<String, String> entries;

    protected AndroidResourceBundle(String bundlePath, Locale locale) {
	this.bundlePath = bundlePath;
	this.locale = locale;
	try {
	    this.entries = fetchEntries(bundlePath);
	} catch (IOException e) {
	    throw new IllegalArgumentException("Could not read bundle " + bundlePath, e);
	}
    }

    Map<String, String> fetchEntries(String bundlePath) throws IOException {
	Map<String, String> result = fetchBaseBundle(bundlePath);
	if (this.locale != null) {
	    Map<String, String> localizedResult = fetchBundle(bundlePath);
	    if (localizedResult != null) {
		result.putAll(localizedResult);
	    }
	}
	return result;
    }

    Map<String, String> fetchBaseBundle(String bundlePath) throws IOException {
	return AndroidResourceConverter.convertToMap(AndroidResourceReader.readBaseBundle(bundlePath));
    }

    Map<String, String> fetchBundle(String bundlePath) throws IOException {
	String xml = AndroidResourceReader.readBundle(bundlePath, this.locale);
	if (xml != null)
	    return AndroidResourceConverter.convertToMap(xml);
	return null;
    }

    @Override
    protected Object handleGetObject(String key) {
	return this.entries.get(key);
    }

    @Override
    public Enumeration<String> getKeys() {
	return new Vector<>(this.entries.values()).elements();
    }

    @Override
    public int hashCode() {
	return Objects.hash(this.locale.getLanguage(), this.bundlePath);
    }

    @Override
    public boolean equals(Object obj) {
	if (obj instanceof AndroidResourceBundle) {
	    AndroidResourceBundle that = (AndroidResourceBundle) obj;
	    return Objects.equals(this.locale.getLanguage(), that.locale.getLanguage())
		    && Objects.equals(this.bundlePath, that.bundlePath);
	}
	return false;
    }
}
